import 'package:play_lab/core/helper/string_format_helper.dart';
import 'package:play_lab/core/utils/url_container.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'dart:convert';

class WsSocketService {
  // static final WsSocketService _instance = WsSocketService._internal();
  // factory WsSocketService() => _instance;
  // WsSocketService._internal();

  late WebSocketChannel _channel;
  String? currentRoom;
  final Map<String, Function(dynamic)> _handlers = {};
  bool _isConnected = false;
  bool get isConnected => _isConnected;
  int _reconnectAttempts = 0;
  static const int maxReconnectAttempts = 5;
  WebSocketChannel get channel => _channel;

  // Initialize connection
  Future<void> connect(String liveTvId) async {
    if (_isConnected) return;

    try {
      _channel = WebSocketChannel.connect(Uri.parse(UrlContainer.socketUrl));

      _channel.stream.listen(
        _handleMessage,
        onError: (error) {
          printX('WebSocket error: $error');
          _reconnect(liveTvId);
        },
        onDone: () {
          printX('WebSocket connection closed');
          _reconnect(liveTvId);
        },
        cancelOnError: true,
      );

      _isConnected = true;
      _reconnectAttempts = 0;

      // Join the room after connection
      joinRoom(liveTvId);
    } catch (e) {
      printX('Connection error: $e');
      _reconnect(liveTvId);
    }
  }

  void joinRoom(String liveTvId) {
    currentRoom = 'live-tv-$liveTvId';
    sendMessage({'type': 'join-live-tv', 'liveTvId': liveTvId});
  }

  void sendMessage(Map<String, dynamic> message) {
    if (!_isConnected) {
      printX('Cannot send message - not connected');
      return;
    }
    _channel.sink.add(jsonEncode(message));
  }

  void _handleMessage(dynamic message) {
    try {
      final data = jsonDecode(message);
      printX('WS Service Data : $data');
      final handler = _handlers[data['type']];

      if (handler != null) {
        handler(data);
      } else {
        printX('No handler for message type: ${data['type']}');
      }
    } catch (e) {
      printX('Error processing message: $e');
    }
  }

  void on(String eventType, Function(dynamic) handler) {
    _handlers[eventType] = handler;
  }

  Future<void> _reconnect(String liveTvId) async {
    if (_reconnectAttempts >= maxReconnectAttempts) {
      printX('Max reconnection attempts reached');
      return;
    }

    _isConnected = false;
    _reconnectAttempts++;
    final delay = Duration(seconds: _reconnectAttempts * 2);

    printX('Reconnecting in ${delay.inSeconds} seconds...');

    await Future.delayed(delay);
    await connect(liveTvId);
  }

  Future<void> disconnect() async {
    try {
      _isConnected = false;
      await _channel.sink.close();
    } catch (e) {
      printX("WS Disconnect error: $e");
    }
  }
}
